/**
 * Copyright © 2013 Creativor Studio.
 * About license information, please see LICENSE.txt.
 */
package org.creativor.rayson.server.transport.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicBoolean;

import org.creativor.rayson.server.transport.http.HttpConnection;
import org.creativor.rayson.share.transport.BufferFormatException;
import org.creativor.rayson.share.transport.http.HttpRequestParser;
import org.creativor.rayson.share.transport.nio.NioConnection;
import org.creativor.rayson.share.transport.nio.ReadBuffer;
import org.creativor.rayson.share.transport.nio.WriteBuffer;

/**
 * Server side {@link NioConnection}.
 * 
 * @author creativor
 */
class ServerNioConnection implements NioConnection {
	private static final int READ_BUFFER_SIZE = 1024 * 1024;
	private static final int WRITE_BUFFER_SIZE = 1024 * 1024;
	private final SocketChannel socketChannel;
	private final AtomicBoolean closed;
	private final ReadBuffer readBuffer;
	private final WriteBuffer writeBuffer;
	private final HttpConnection httpConn;

	/**
	 * @param address
	 */
	ServerNioConnection(final SocketChannel socketChannel,
			final SelectionKey selectionKey) {
		this.socketChannel = socketChannel;
		final ByteBuffer bb = ByteBuffer.allocate(READ_BUFFER_SIZE);
		final HttpRequestParser parser = new HttpRequestParser(bb);
		readBuffer = new ReadBuffer(bb, socketChannel, parser);
		writeBuffer = new WriteBuffer(WRITE_BUFFER_SIZE, socketChannel,
				selectionKey);
		closed = new AtomicBoolean();
		httpConn = new HttpConnection(socketChannel, readBuffer, writeBuffer,
				parser);
	}

	@Override
	public int asyncRead() throws IOException {
		final int result = readBuffer.fill();
		if (result > 0)
			try {
				httpConn.asyncRead();
			} catch (final BufferFormatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		return result;
	}

	@Override
	public void asyncWrite() throws IOException {
		writeBuffer.asyncWrite();
	}

	@Override
	public void close() throws IOException {
		if (!closed.compareAndSet(false, true))
			return;
		if (this.socketChannel != null)
			this.socketChannel.close();

	}

	@Override
	public ReadBuffer getReadBuffer() {
		return readBuffer;
	}

	@Override
	public WriteBuffer getWriteBuffer() {
		return writeBuffer;
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("socketChannel:" + this.socketChannel);
		sb.append("}");
		return sb.toString();
	}

}